package com.moons.cameracrop;

import android.Manifest;
import android.graphics.Point;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Toast;

import com.jiangdg.usbcamera.UVCCameraHelper;
import com.jiangdg.usbcamera.utils.FileUtils;
import com.moons.cameracrop.databinding.ActivityMainBinding;
import com.serenegiant.usb.CameraDialog;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.common.AbstractUVCCameraHandler;
import com.serenegiant.usb.widget.CameraViewInterface;
import com.tbruyelle.rxpermissions3.RxPermissions;

import java.util.ArrayList;
import java.util.List;

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;

public class MainActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent, CameraViewInterface.Callback {
    private final String TAG = this.getClass().getSimpleName();

    private ActivityMainBinding mBinding;
    private UVCCameraHelper mCameraHelper;
    private CameraViewInterface mUVCCameraView;

    private boolean isRequest;
    private boolean isPreview;

    private int previewWidth = 1280;
    private int previewHeight = 720;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());


        RxPermissions rxPermissions = new RxPermissions(this);

        rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(granted -> {
                    Log.i(TAG, "onCreate granted: " + granted);
                    if (granted) {

                        initViews();

                    } else {

                        finish();
                    }

                });


    }

    private void initViews() {

        mUVCCameraView = (CameraViewInterface) mBinding.cameraView;
        mUVCCameraView.setCallback(this);
        mCameraHelper = UVCCameraHelper.getInstance();
        mCameraHelper.setDefaultPreviewSize(previewWidth, previewHeight);
        mCameraHelper.setDefaultFrameFormat(UVCCameraHelper.FRAME_FORMAT_MJPEG);
        mCameraHelper.initUSBMonitor(this, mUVCCameraView, listener);

        mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
            @Override
            public void onPreviewResult(byte[] nv21Yuv) {
//                Log.d(TAG, "onPreviewResult: " + nv21Yuv.length);
            }
        });
        mBinding.rbDefault.setChecked(true);
        mBinding.rgScaleType.setOnCheckedChangeListener((group, checkedId) -> {

//            mCameraHelper.updateResolution(previewWidth, previewHeight);
            int checkedRadioButtonId = mBinding.rgScaleType.getCheckedRadioButtonId();

            Log.d(TAG, "initViews checkedRadioButtonId: " + checkedRadioButtonId);

            if (checkedRadioButtonId == mBinding.rbDefault.getId()) {

                defaultSizePreview();

            } else {

                cropPreview();
            }


        });


    }

    private UVCCameraHelper.OnMyDevConnectListener listener = new UVCCameraHelper.OnMyDevConnectListener() {

        @Override
        public void onAttachDev(UsbDevice device) {
            // request open permission
            if (!isRequest) {
                isRequest = true;
                if (mCameraHelper != null) {

                    int index = -1;
                    for (int i = 0; i < mCameraHelper.getUsbDeviceList().size(); i++) {

                        String productName = mCameraHelper.getUsbDeviceList().get(i).getProductName();
                        if (!TextUtils.isEmpty(productName) && productName.contains("SVS RGB USB camera")) {
                            index = i;
                        }

                    }

                    if (index == -1) {

                        showShortMsg("未找到 RGB camera 设备");


                    } else {
                        mCameraHelper.requestPermission(index);
                    }


                    Log.d(TAG, "onAttachDev index: " + index);
//                    for (UsbDevice usbDevice : mCameraHelper.getUsbDeviceList()) {
//                        Log.d(TAG, "onAttachDev: " + usbDevice.toString());
//                    }

                }
            }
        }

        @Override
        public void onDettachDev(UsbDevice device) {
            // close camera
            if (isRequest) {
                isRequest = false;
                mCameraHelper.closeCamera();
                showShortMsg(device.getDeviceName() + " is out");
            }
        }

        @Override
        public void onConnectDev(UsbDevice device, boolean isConnected) {
            if (!isConnected) {
                showShortMsg("fail to connect,please check resolution params");
                isPreview = false;
            } else {
                isPreview = true;
                showShortMsg("connecting");

                // initialize seekbar
                // need to wait UVCCamera initialize over
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(2500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Looper.prepare();
                        if (mCameraHelper != null && mCameraHelper.isCameraOpened()) {

//                            mSeekBrightness.setProgress(mCameraHelper.getModelValue(UVCCameraHelper.MODE_BRIGHTNESS));
//                            mSeekContrast.setProgress(mCameraHelper.getModelValue(UVCCameraHelper.MODE_CONTRAST));

                        }
                        Looper.loop();
                    }
                }).start();
            }
        }

        @Override
        public void onDisConnectDev(UsbDevice device) {
            showShortMsg("disconnecting");
        }
    };

    private void cropPreview() {
        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Point point = new Point();
        windowManager.getDefaultDisplay().getSize(point);
        int screenWidth = point.x;
        int screenHeight = point.y;

        ViewGroup.LayoutParams params = mBinding.cameraView.getLayoutParams();
        int layoutWidth = params.width;
        int layoutHeight = params.height;


        float capRatio = previewWidth * 1.0f / previewHeight;
        float viewRatio = layoutWidth * 1.0f / layoutHeight;

        if (capRatio != viewRatio) {
            int newLayWidth = screenHeight * previewWidth / previewHeight;
            ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(newLayWidth, screenHeight);
            layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
            layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
            layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
            layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
//                layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);

            Log.d(TAG, "onConnectDev: " + layoutParams.height);
            Log.d(TAG, "onConnectDev: " + layoutParams.width);

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mBinding.cameraView.setLayoutParams(layoutParams);
                    mBinding.cameraView.requestLayout();
                }
            });

        }
    }

    private void defaultSizePreview() {

        ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
        layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
        layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
        layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mBinding.cameraView.setLayoutParams(layoutParams);
                mBinding.cameraView.requestLayout();
            }
        });
    }


    private List<String> getResolutionList() {
        List<Size> list = mCameraHelper.getSupportedPreviewSizes();
        List<String> resolutions = null;
        if (list != null && list.size() != 0) {
            resolutions = new ArrayList<>();
            for (Size size : list) {
                if (size != null) {
                    resolutions.add(size.width + "x" + size.height);
                }
            }
        }
        return resolutions;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        FileUtils.releaseFile();
        // step.4 release uvc camera resources
        if (mCameraHelper != null) {
            mCameraHelper.release();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        // step.2 register USB event broadcast
        if (mCameraHelper != null) {
            mCameraHelper.registerUSB();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        // step.3 unregister USB event broadcast
        if (mCameraHelper != null) {
            mCameraHelper.unregisterUSB();
        }
    }

    private void showShortMsg(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public USBMonitor getUSBMonitor() {
        return mCameraHelper.getUSBMonitor();
    }

    @Override
    public void onDialogResult(boolean canceled) {
        if (canceled) {
            showShortMsg("取消操作");
        }
    }

    public boolean isCameraOpened() {
        return mCameraHelper.isCameraOpened();
    }

    @Override
    public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
        Log.d(TAG, "onSurfaceCreated: ");
        if (!isPreview && mCameraHelper.isCameraOpened()) {

            mCameraHelper.startPreview(mUVCCameraView);

            isPreview = true;
        }
    }

    @Override
    public void onSurfaceChanged(CameraViewInterface view, Surface surface, int width, int height) {
        Log.d(TAG, "onSurfaceChanged: " + width);
        Log.d(TAG, "onSurfaceChanged: " + height);

        if (isPreview && mCameraHelper.isCameraOpened()) {

            mCameraHelper.stopPreview();

            mCameraHelper.startPreview(mUVCCameraView);

            isPreview = true;

        }


    }

    @Override
    public void onSurfaceDestroy(CameraViewInterface view, Surface surface) {
        Log.d(TAG, "onSurfaceDestroy: ");

        if (isPreview && mCameraHelper.isCameraOpened()) {
            mCameraHelper.stopPreview();
            isPreview = false;
        }
    }
}